/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Server;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.text.DefaultCaret;

/**
 *
 * @author TienNT
 */
public class ServerControl extends javax.swing.JFrame {

    ControlThread mControlThread;
    boolean isStarted = false;

    /**
     * Creates new form ServerControl
     */
    public ServerControl() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        txtLog = new javax.swing.JTextArea();
        btnStart = new javax.swing.JButton();
        btnStop = new javax.swing.JButton();
        btnClearLog = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        txtODBC = new javax.swing.JTextField();
        btnKick = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Server Control");
        setLocationByPlatform(true);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        DefaultCaret caret = (DefaultCaret)txtLog.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        txtLog.setEditable(false);
        txtLog.setColumns(20);
        txtLog.setFont(new java.awt.Font("Lucida Console", 0, 12)); // NOI18N
        txtLog.setRows(5);
        jScrollPane1.setViewportView(txtLog);

        btnStart.setText("Start");
        btnStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnStartActionPerformed(evt);
            }
        });

        btnStop.setText("Stop");
        btnStop.setEnabled(false);
        btnStop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnStopActionPerformed(evt);
            }
        });

        btnClearLog.setText("Clear log");
        btnClearLog.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnClearLogActionPerformed(evt);
            }
        });

        jLabel1.setText("DNS name");

        txtODBC.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                txtODBCActionPerformed(evt);
            }
        });

        btnKick.setText("Kick");
        btnKick.setEnabled(false);
        btnKick.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnKickActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(btnStart)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnStop)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnClearLog)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnKick)
                        .addGap(12, 12, 12)
                        .addComponent(jLabel1)
                        .addGap(18, 18, 18)
                        .addComponent(txtODBC, javax.swing.GroupLayout.DEFAULT_SIZE, 152, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnStart)
                    .addComponent(btnStop)
                    .addComponent(btnClearLog)
                    .addComponent(jLabel1)
                    .addComponent(txtODBC, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnKick))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 331, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStartActionPerformed
        try {
            // TODO add your handling code here:
            DatabaseAdapter mTest = new DatabaseAdapter(txtODBC.getText().trim());
            mTest.driverTest();
            txtODBC.setEditable(false);
            mControlThread = new ControlThread();
            mControlThread.start();
            isStarted = true;
        } catch (ClassNotFoundException | SQLException ex) {
            JOptionPane.showMessageDialog(this, "Invalid DSN", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btnStartActionPerformed

    private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopActionPerformed
        mControlThread.stop = true;
        btnStart.setEnabled(true);
        btnStop.setEnabled(false);
        btnKick.setEnabled(false);
        try {
            Socket tempSocket = new Socket("localhost", 1233);
            PrintWriter tempWriter = new PrintWriter(tempSocket.getOutputStream(), true);
            tempWriter.println("" + ServerUtils.STOP_SERVER);
            tempWriter.close();
            tempSocket.close();

            Set servThreadList = (Set) ServThread.mSocketTable.keySet();
            for (Iterator i = servThreadList.iterator(); i.hasNext();) {
                String k = (String) i.next();
                ServThread.mSocketTable.get(k).kickRequested();
            }

            mControlThread.closeServerSocket();
            System.out.println(tempSocket.isClosed());
        } catch (UnknownHostException ex) {
            Logger.getLogger(ServerControl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ServerControl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_btnStopActionPerformed

    private void btnClearLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearLogActionPerformed
        // TODO add your handling code here:
        txtLog.setText("");
    }//GEN-LAST:event_btnClearLogActionPerformed

    private void txtODBCActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtODBCActionPerformed
        // TODO add your handling code here:
        btnStartActionPerformed(evt);
    }//GEN-LAST:event_txtODBCActionPerformed

    private void btnKickActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnKickActionPerformed
        // TODO add your handling code here:
        new Kick();
    }//GEN-LAST:event_btnKickActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        // TODO add your handling code here:
        if (isStarted) {
            mControlThread.stop = true;
            btnStart.setEnabled(true);
            btnStop.setEnabled(false);
            btnKick.setEnabled(false);
            try {
                Socket tempSocket = new Socket("localhost", 1233);
                PrintWriter tempWriter = new PrintWriter(tempSocket.getOutputStream(), true);
                tempWriter.println("" + ServerUtils.STOP_SERVER);
                tempWriter.close();
                tempSocket.close();

                Object[] s = ServThread.mSocketTable.keySet().toArray();
                for (Object o : s) {
                    ServThread.mSocketTable.get((String) o).kickRequested();
                }
                mControlThread.closeServerSocket();
            } catch (UnknownHostException ex) {
                Logger.getLogger(ServerControl.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(ServerControl.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        dispose();;
    }//GEN-LAST:event_formWindowClosing

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
        }
        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ServerControl().setVisible(true);
            }
        });
    }

    public class ControlThread extends Thread {

        public boolean stop = false;
        private ServerSocket mServerSocket = null;

        @Override
        public void run() {
            Calendar calendar = Calendar.getInstance();
            String date = "" + calendar.get(Calendar.DAY_OF_MONTH) + "-" + calendar.get(Calendar.MONTH) + "-" + calendar.get(Calendar.YEAR);
            date += "   " + calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE) + ":" + calendar.get(Calendar.SECOND);
            appendLog("Started: " + date);

            try {
                mServerSocket = new ServerSocket(1233);
                appendLog("Listening on port: 1233");
                btnStart.setEnabled(false);
                btnStop.setEnabled(true);
                btnKick.setEnabled(true);
            } catch (IOException exception) {
            }
            while (!stop) {
                try {
                    Socket socket = mServerSocket.accept();
                    new ServThread(this, socket, txtODBC.getText().trim()).start();

                } catch (SQLException | IOException ex) {
                    Logger.getLogger(ServerControl.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        public void appendLog(String log) {
            txtLog.append(log + "\n");
        }

        public void closeServerSocket() {
            if (mServerSocket != null) {
                try {
                    mServerSocket.close();
                } catch (IOException ex) {
                    Logger.getLogger(ServerControl.class.getName()).log(Level.SEVERE, null, ex);
                }
                ;
            }
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnClearLog;
    private javax.swing.JButton btnKick;
    private javax.swing.JButton btnStart;
    private javax.swing.JButton btnStop;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea txtLog;
    private javax.swing.JTextField txtODBC;
    // End of variables declaration//GEN-END:variables
}
